package webhook

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"log"
	"strings"

	"gitee.com/daofeixian/dfx_golang_toolset/sendmsg"
	"gitee.com/daofeixian/dfx_golang_toolset/utils"
)

// 常量定义
const (
	DingdingMsgTypeText     = "text"
	DingdingMsgTypeMarkdown = "markdown"
	DingdingContentTypeJSON = "application/json"
	DingdingDefaultTitle    = "来自dfx_golang_toolset的消息"
)

// DingdingWebhook 钉钉Webhook发送消息的实现类
type DingdingWebhook struct{}

// 确保DingdingWebhook实现了SendMsgTer接口
var _ sendmsg.SendMsgTer = (*DingdingWebhook)(nil)

// SendMsg 发送消息到钉钉Webhook
// 参数:
//   - sendinfo: 包含发送信息的结构体，不能为空
//
// 返回值:
//   - error: 发送过程中可能发生的错误
func (d *DingdingWebhook) SendMsg(ctx context.Context, sendinfo *sendmsg.SendInfo) error {
	if sendinfo == nil {
		return fmt.Errorf("发送信息不能为空")
	}

	ddMsg := NewDingdingWebhookMap(sendinfo.MsgType, sendinfo.Msg, sendinfo.Template, sendinfo.PhoneNumbers)
	jsonBody, err := json.Marshal(ddMsg)
	if err != nil {
		return fmt.Errorf("消息序列化失败: %w", err)
	}

	headers := map[string]interface{}{
		"Content-Type": DingdingContentTypeJSON,
	}

	log.Printf("Dingding webhook request: %s", string(jsonBody))

	resqBody, err := utils.HttpDo(ctx, sendinfo.Url, "POST", bytes.NewReader(jsonBody), headers)
	if err != nil {
		return fmt.Errorf("发送请求失败: %w", err)
	}

	log.Printf("Dingding webhook response: %s", string(resqBody))
	return nil
}

// DingdingAtmsg 钉钉@消息结构体
type DingdingAtmsg struct {
	AtMobiles []string `json:"atMobiles"`
}

// NewDingdingAtmsg 创建钉钉@消息对象
// 参数:
//   - mobile: 要@的手机号列表
//
// 返回值:
//   - *DingdingAtmsg: 新创建的@消息对象
func NewDingdingAtmsg(mobile []string) *DingdingAtmsg {
	return &DingdingAtmsg{
		AtMobiles: mobile,
	}
}

// DingdingTextMsg 钉钉文本消息结构体
type DingdingTextMsg struct {
	Content string `json:"content"`
}

// NewDingdingTextMsg 创建钉钉文本消息对象
// 参数:
//   - content: 消息内容
//   - temptext: 模板文本
//
// 返回值:
//   - *DingdingTextMsg: 新创建的文本消息对象
func NewDingdingTextMsg(content, temptext string) *DingdingTextMsg {
	content = JsonDataToTemplate(content, temptext)
	if content == "" || content == WebhookFailureMsg {
		content = WebhookFailureMsg
	}

	return &DingdingTextMsg{
		Content: content,
	}
}

// DingdingMarkdownMsg 钉钉Markdown消息结构体
type DingdingMarkdownMsg struct {
	Title string `json:"title"`
	Text  string `json:"text"`
}

// NewDingdingMarkdownMsg 创建钉钉Markdown消息对象
// 参数:
//   - title: 消息标题
//   - content: 消息内容
//   - temptext: 模板文本
//   - mobile: 要@的手机号列表
//
// 返回值:
//   - *DingdingMarkdownMsg: 新创建的Markdown消息对象
func NewDingdingMarkdownMsg(title, content, temptext string, mobile []string) *DingdingMarkdownMsg {
	content = JsonDataToTemplate(content, temptext)
	if content == "" || content == WebhookFailureMsg {
		content = WebhookFailureMsg
	}

	// 添加@手机号
	if len(mobile) > 0 {
		var mobiles strings.Builder
		for _, phone := range mobile {
			mobiles.WriteString("@")
			mobiles.WriteString(phone)
			mobiles.WriteString(" ")
		}
		content = content + "\n\n" + mobiles.String()
	}

	return &DingdingMarkdownMsg{
		Title: title,
		Text:  content,
	}
}

// NewDingdingWebhookMap 根据消息类型创建对应的钉钉消息结构体
// 参数:
//   - msgType: 消息类型（text 或 markdown）
//   - content: 消息内容
//   - temptext: 模板文本
//   - mobile: 要@的手机号列表
//
// 返回值:
//   - map[string]interface{}: 构造好的钉钉消息映射
func NewDingdingWebhookMap(msgType, content, temptext string, mobile []string) map[string]interface{} {
	mapMsg := map[string]interface{}{
		"at": NewDingdingAtmsg(mobile),
	}

	switch msgType {
	case DingdingMsgTypeText:
		mapMsg["msgtype"] = DingdingMsgTypeText
		mapMsg["text"] = NewDingdingTextMsg(content, temptext)
	case DingdingMsgTypeMarkdown:
		mapMsg["msgtype"] = DingdingMsgTypeMarkdown
		mapMsg["markdown"] = NewDingdingMarkdownMsg(DingdingDefaultTitle, content, temptext, mobile)
	default:
		// 默认使用文本类型，并显示错误信息
		errorContent := "{\"msg\":\"不支持的消息类型: " + msgType + "\"}"
		errorTemplate := "{{.msg}}"
		mapMsg["msgtype"] = DingdingMsgTypeText
		mapMsg["text"] = NewDingdingTextMsg(errorContent, errorTemplate)
	}

	return mapMsg
}
